package com.ming_za.odupdaterserver.core.config;

import com.ming_za.odupdaterserver.core.config.type.*;
import com.ming_za.odupdaterserver.core.sqlite.domain.Config;
import com.ming_za.odupdaterserver.core.sqlite.mapper.ConfigMapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * 基础配置类
 * <p>该类用于对基础/全局配置内容操作</p>
 * <p>通过sqlite进行数据存储</p>
 */
@DependsOn("dataSourceInitializer")
@MapperScan("com.ming_za.odupdaterserver.core.sqlite.mapper")
@Repository
public class ConfigManager {

    private final Random random = new Random(System.currentTimeMillis());

    /**
     * 通过sqlite获取配置的方法接口
     */
    public final Function<String,String> getter = new Function<>() {
        @Override
        public String apply(String key) {

            Config config = configMapper.selectByPrimaryKey(key);
            if (config == null) {
                return null;
            }
            return config.getValue();
        }
    };

    /**
     * 通过sqlite存储配置的方法接口
     */
    public final BiConsumer<String,String> setter = new BiConsumer<>() {
        @Override
        public void accept(String key, String value) {
            if (configMapper.updateValue(key,value) == 0){
                configMapper.insert(key, value);
            }
        }
    };

    private final ConfigMapper configMapper;

    private final Map<String,ValueType<?>> allValueTypes = new HashMap<>();

    public ConfigManager(ConfigMapper configMapper) {
        this.configMapper = configMapper;

        //服务端口 默认：26666
        allValueTypes.put("port",new IntValue("port",26666,getter,setter));

        //服务端最大占用的总宽带
        allValueTypes.put("maxDownloadBroadband",new IntValue("maxDownloadBroadband",10,getter,setter));

        //单个下载通道最大占用宽带 默认：2,单位：M
        allValueTypes.put("maxSingleDownloadBroadband",new IntValue("maxSingleDownloadBroadband",2,getter,setter));

        //单个ip最大并发下载 默认：3
        allValueTypes.put("maxConcurrentDownload",new IntValue("maxConcurrentDownload",3,getter,setter));

        //资源文件，以运行目录为根目录，该文件夹路径正常使用后不建议修改
        allValueTypes.put("resFold",new StringValue("resFold",".\\res",getter,setter));

        /*
        缓存，默认：开启(true)
        原理：
            开启后会将数据库中的信息对象保存到内存中，便于计算与增删改查，提高性能
            当程序内存溢出时会尝试关闭改设置继续运行
        优点：
            减少硬盘读取次数
            提高资源计算速率
        缺点：
            开启缓存后会占用更多的内存（随着资源内容增多而加大）
        建议：
            程序运行内存大于2G时建议开启，优化性能
        当前缓存内容：
            数据库中的资源信息等缓存
            数据库中的标签信息缓存
            数据库中主版本号缓存
         */
        allValueTypes.put("cache",new BooleanValue("cache",true,getter,setter));

        //雪花算法，机器id，限制0~31
        allValueTypes.put("snowflakeWorkerId",new LongValue("snowflakeWorkerId",0L,getter,setter));

        //雪花算法，数据中心id，限制0~31
        allValueTypes.put("snowflakeDatacenterId",new LongValue("snowflakeDatacenterId",0L,getter,setter));

        //雪花算法，开始时间戳
        LongValue snowflakeStartTime = new LongValue("snowflakeStartTimestamp",0L,getter,setter);
        if (snowflakeStartTime.getValue() == 0){
            snowflakeStartTime.setValue(System.currentTimeMillis());
        }
        allValueTypes.put("snowflakeStartTimestamp",snowflakeStartTime);

        //雪花算法，最后一次生成时间戳
        allValueTypes.put("snowflakeLastTimestamp",new LongValue("snowflakeLastTimestamp",0L,getter,setter));

        //资源文件后缀
        allValueTypes.put("resFileSuffix",new StringValue("resFileSuffix",".odres",getter,setter));

        //任务并发数量
        allValueTypes.put("taskConcurrentCount",new IntValue("taskConcurrentCount",100,getter,setter));

        //管理账户安全相关=================================

        //开启登录验证
        allValueTypes.put("loginVerification",new BooleanValue("loginVerification",false,getter,setter));

        //允许密码错误次数,0表示无限制
        allValueTypes.put("allowPasswordErrorCount",new IntValue("allowPasswordErrorCount",3,getter,setter));

        //验证锁定时间，单位（分钟），0表示无限
        allValueTypes.put("verificationLockTime",new IntValue("verificationLockTime",10,getter,setter));

        //频繁异地登录锁定
        allValueTypes.put("frequentRemoteLock",new BooleanValue("frequentRemoteLock",true,getter,setter));

        //其他==============================================
        //未发布资源密钥，通过该密钥获取未发布版本的资源
        allValueTypes.put("unpublishedSecretKey",new IntValue("unpublishedSecretKey",getRandomIntSecretKey(),getter,setter));
    }

    //============================================

    public IntValue getPort(){
        return (IntValue) allValueTypes.get("port");
    }

    public IntValue getMaxDownloadBroadband(){
        return (IntValue) allValueTypes.get("maxDownloadBroadband");
    }

    public IntValue getMaxSingleDownloadBroadband(){
        return (IntValue) allValueTypes.get("maxSingleDownloadBroadband");
    }

    public IntValue getMaxConcurrentDownload(){
        return (IntValue) allValueTypes.get("maxConcurrentDownload");
    }

    public StringValue getResFold(){
        return (StringValue) allValueTypes.get("resFold");
    }

    public BooleanValue getCache(){
        return (BooleanValue) allValueTypes.get("cache");
    }

    public LongValue getSnowflakeWorkerId(){
        return (LongValue) allValueTypes.get("snowflakeWorkerId");
    }

    public LongValue getSnowflakeDatacenterId(){
        return (LongValue) allValueTypes.get("snowflakeDatacenterId");
    }

    public LongValue getSnowflakeStartTimestamp(){
        return (LongValue) allValueTypes.get("snowflakeStartTimestamp");
    }

    public LongValue getSnowflakeLastTimestamp(){
        return (LongValue) allValueTypes.get("snowflakeLastTimestamp");
    }

    public StringValue getResFileSuffix(){
        return (StringValue) allValueTypes.get("resFileSuffix");
    }

    public BooleanValue getLoginVerification(){
        return (BooleanValue) allValueTypes.get("loginVerification");
    }

    public IntValue getAllowPasswordErrorCount(){
        return (IntValue) allValueTypes.get("allowPasswordErrorCount");
    }

    public IntValue getVerificationLockTime(){
        return (IntValue) allValueTypes.get("verificationLockTime");
    }

    public BooleanValue getFrequentRemoteLock(){
        return (BooleanValue) allValueTypes.get("frequentRemoteLock");
    }

    public IntValue getUnpublishedSecretKey(){
        return (IntValue) allValueTypes.get("unpublishedSecretKey");
    }

    public IntValue getTaskConcurrentCount(){
        return (IntValue) allValueTypes.get("taskConcurrentCount");
    }

    /**
     * 生成随机未发布密钥
     * @return 生成的密钥
     */
    public int generateRandomUnpublishedSecretKey(){
        int key = getRandomIntSecretKey();
        getUnpublishedSecretKey().saveValue(key);
        return key;
    }

    private int getRandomIntSecretKey(){
        return (random.nextInt() | 0x80000000) ^ 0x80000000;
    }

    /**
     * 重载所有配置value
     */
    public void reloadAllValue(){
        for(ValueType<?> valueType : allValueTypes.values()){
            valueType.loadValue();
        }
    }

}
